#!/usr/bin/python3
#
# Copyright 2018 Google LLC. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
"""This script is used to generate license notice string for packager."""

import argparse
import os
import sys

LICENSE_FILES = set(['LICENSE', 'LICENSE.TXT', 'COPYING'])
PRUNE_PATHS = [
    # Used for testing, not in the binary build.
    os.path.join('third_party', 'json'),
    os.path.join('third_party', 'googletest'),

    # Dependencies of dependencies, not actually used in Packager.
    os.path.join('third_party', 'libpng', 'source', 'contrib'),

    # The Java side of icu, not used in Packager.
    os.path.join('third_party', 'icu', 'source', 'icu4j'),

    # Misc. ICU scripts, not used in Packager.
    os.path.join('third_party', 'icu', 'scripts'),
]

CC_FILE_TEMPLATE = """
// Generated by tools/generate_license_notice.py. Do not modify.

namespace shaka {{

const char* kLicenseNotice[] = {{
{}
}};

}}  // namespace shaka"""

H_FILE_TEMPLATE = """
// Generated by tools/generate_license_notice.py. Do not modify.

#ifndef PACKAGER_TOOLS_LICENSE_NOTICE_H_
#define PACKAGER_TOOLS_LICENSE_NOTICE_H_

namespace shaka {{
extern const char* kLicenseNotice[{}];
}}  // namespace shaka

#endif  // PACKAGER_TOOLS_LICENSE_NOTICE_H_"""


def _FindLicenseFiles(root):
  """Finds and returns all license files."""
  result = []
  for path, dirs, files in os.walk(root):
    path = path[len(root) + 1:]  # Change to relative path.

    if path in PRUNE_PATHS:
      dirs[:] = []
      continue

    license_files = LICENSE_FILES.intersection(files)
    if license_files:
      result.append(os.path.join(path, license_files.pop()))
  return result


def _GetModuleName(path):
  """Find third_party module name from file path."""
  while True:
    path = os.path.dirname(path)
    base_name = os.path.basename(path)
    if base_name not in ['src', 'source', 'trunk']:
      return base_name


def _ReadFile(path):
  """Reads a file from disk."""
  with open(path, 'rb') as f:
    return f.read().splitlines()


def GenerateLicenseNotice(output_dir, output_license_file_name):
  """Generate plain-text license notice embedded in C++ code.

  The output file contains licenses of both Shaka Packager and third-party
  libraries used in Shaka Packager.

  Args:
    output_dir: Output directory path. If not specified, no output is produced.
    output_license_file_name: Whether to output license file names.
  """

  script_dir = os.path.dirname(os.path.realpath(__file__))
  packager_dir = os.path.abspath(os.path.join(script_dir, os.pardir))

  license_files = _FindLicenseFiles(packager_dir)
  license_files.sort()

  if output_license_file_name:
    print('Num License Files: {}\n'.format(len(license_files)))
    for license_file in license_files:
      print(license_file)

  # Include the main license file.
  content = _ReadFile(os.path.join(packager_dir, os.pardir, 'LICENSE'))
  for license_file in license_files:
    content.append('-' * 20)
    content.append(_GetModuleName(license_file))
    content.append('-' * 20)
    content.extend(_ReadFile(os.path.join(packager_dir, license_file)))

  # MSVC does not like long strings (Error C2026, C1091), so we have to break
  # them into multiple strings.
  content_array_text = '\n'.join(map('    R"shaka({})shaka",'.format, content))

  if output_dir:
    cc_file_path = os.path.join(output_dir, 'license_notice.cc')
    with open(cc_file_path, 'w', encoding='utf8') as output:
      output.write(CC_FILE_TEMPLATE.format(content_array_text))

    h_file_path = os.path.join(output_dir, 'license_notice.h')
    with open(h_file_path, 'w', encoding='utf8') as output:
      output.write(H_FILE_TEMPLATE.format(len(content)))


def main():
  parser = argparse.ArgumentParser()

  parser.add_argument(
      '--output-license-file-name',
      dest='output_license_file_name',
      action='store_true')
  parser.set_defaults(output_license_file_name=False)

  parser.add_argument('output_dir', nargs='?')
  args = parser.parse_args()

  GenerateLicenseNotice(args.output_dir, args.output_license_file_name)
  return 0


if __name__ == '__main__':
  sys.exit(main())
